package se.djupfeldt.oscar.logbook;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import se.djupfeldt.oscar.logbook.console.ConsoleHandler;
import se.djupfeldt.oscar.logbook.database.DatabaseHandler;
import se.djupfeldt.oscar.logbook.database.DatabaseHandler.DB_RESULT;
import se.djupfeldt.oscar.logbook.datasource.SentenceInjector;
import se.djupfeldt.oscar.logbook.datasource.SerialComm;
import se.djupfeldt.oscar.logbook.server.ServerHandler;
import se.djupfeldt.oscar.logbook.utils.TypedProperties;


public class Logbook {
    public static SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd HH.mm.ss z");
    public static final TypedProperties properties = new TypedProperties();
    
    private static String source = "serial";
    
    private static Logger log = Logger.getLogger(Logbook.class);

    public static String getCurrentDateString() {
	Date d = Calendar.getInstance().getTime();
	return sdf.format(d);
    }

    public static void main(String[] args) {
	PropertyConfigurator.configure("config/log4j.cfg");
	
	try {
	    properties.load(new FileInputStream("config/logbook.cfg"));
	} catch (FileNotFoundException e) {
	    log.error("Configuration file 'logbook.cfg' not found. Exiting", e);
	    System.exit(1);
	} catch (IOException e) {
	    log.error("I/O Exception", e);
	}
	
	for (String arg : args) {
	    String[] parts = arg.split("=");
	    if (parts.length != 2 && !arg.startsWith("-")) {
		log.error("Erroneous argument: " + arg + ". Syntax is key=value");
		System.exit(0);
	    } else if (parts.length == 2) {
		handleKeyValue(parts);
	    } else if (arg.startsWith("-")) {
		handleKey(arg);
	    } else {
		log.error("Erroneous argument: " + arg + ". Syntax is key=value");
		System.exit(0);
	    }
	}

	try {
	    if (source.equalsIgnoreCase("serial")) {
		SerialComm nmeaSerial = new SerialComm();
		nmeaSerial.init();
		nmeaSerial.start();
	    } else if (source.equalsIgnoreCase("injector")) {
		SentenceInjector inj = new SentenceInjector();
		inj.init();
		inj.start();
	    }
	} catch (IllegalArgumentException e) {
	    log.error(e.getMessage(), e);
	    System.exit(-1);
	} catch (SecurityException e) {
	    log.error(e.getMessage(), e);
	    System.exit(-1);
	}
	
	ConsoleHandler ch = ConsoleHandler.getInstance();
	ch.initCommands();
	ch.start();
	
	ServerHandler sh = ServerHandler.getInstance();
	if (sh.init()) {
	    sh.start();
	} else {
	    log.error("Could initialize Server. Exiting.");
	    System.exit(-1);
	}
    }

    private static void handleKey(String arg) {
	if (arg.equalsIgnoreCase("-initdb")) {
	    DB_RESULT res = DatabaseHandler.getInstance().init();
	    switch (res) {
	    case INIT_OK_DB_CREATED:
		log.info("Database created and opened.");
		return;
	    case INIT_OK_DB_EXISTS:
		log.info("Database opened.");
		return;
	    case INIT_ERROR:
		log.error("Database could not be created or opened.");
		System.exit(0);
	    default:
		System.exit(0);
	    }
	}
	if (arg.equalsIgnoreCase("-resetdb")) {
	    DB_RESULT res = DatabaseHandler.getInstance().init(true);
	    switch (res) {
	    case INIT_OK_DB_CREATED:
		log.info("Database reset and opened.");
		return;
	    case INIT_OK_DB_EXISTS:
		log.error("Database could not be reset.");
		System.exit(0);
	    case INIT_ERROR:
		log.error("Database could not be reset or opened.");
		System.exit(0);
	    default:
		System.exit(0);
	    }
	}
    }

    private static void handleKeyValue(String[] parts) {
	String key = parts[0];
	String value = parts[1];
	if (key.equals("source")) {
	    log.info("Using " + source + " as NMEA source.");
	    source = value;
	}
    }
}
